package com.tongan.generate;

import com.tongan.generate.tinyextend.MyCodeGenerator;
import com.tongan.generate.tinyextend.NewMetadata;
import com.tongan.util.CodeResourceUtil;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import jodd.util.SystemUtil;
import lombok.Data;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.tinygroup.codegen.CodeGenerator;
import org.tinygroup.context.Context;
import org.tinygroup.context.util.ContextFactory;
import org.tinygroup.docgen.impl.DocumentGeneraterImpl;
import org.tinygroup.template.impl.TemplateEngineDefault;
import org.tinygroup.template.loader.FileObjectResourceLoader;
import org.tinygroup.template.loader.FileResourceManager;

import java.io.*;
import java.nio.file.Paths;
import java.util.Map;

@Data
public class CgformCodeFactory extends BaseCodeFactory {
   private ICallBack callBack;
   private String projectPath;
   private TemplateEngineType engineType;
   TemplateEngineDefault templateEngineDefault;
   NewMetadata newMetadata;

   public CgformCodeFactory() {
      //tiny模版及相关实例
      MyCodeGenerator codeGeneratorDefault=new MyCodeGenerator();
      DocumentGeneraterImpl documentGenerater=new DocumentGeneraterImpl();
      templateEngineDefault=new TemplateEngineDefault();
      templateEngineDefault.setEncode("utf-8");
      templateEngineDefault.setCheckModified(true);
      FileResourceManager fileResourceManager=new FileResourceManager();
      FileObjectResourceLoader fileObjectResourceLoader=new FileObjectResourceLoader();
      fileObjectResourceLoader.setFileResourceManager(fileResourceManager);
      templateEngineDefault.addResourceLoader(fileObjectResourceLoader);

      documentGenerater.setTemplateGenerater(templateEngineDefault);
      documentGenerater.setFileResourceManager(fileResourceManager);
      codeGeneratorDefault.setGenerater(documentGenerater);
      generator=codeGeneratorDefault;
   }

   public void generateFile(String templateFileName, String type, Map data) throws TemplateException, IOException {
      try {
         String entityPackage = data.get("entityPackage").toString();
         String entityName = data.get("entityName").toString();
         String fileNamePath = this.getCodePath(type, entityPackage, entityName);
         String fileDir = StringUtils.substringBeforeLast(fileNamePath, "/");
         Template template = this.getConfiguration().getTemplate(templateFileName);
         FileUtils.forceMkdir(new File(fileDir + "/"));
         Writer out = new OutputStreamWriter(new FileOutputStream(fileNamePath), CodeResourceUtil.SYSTEM_ENCODING);
         template.process(data, out);
         out.close();
      } catch (TemplateException var10) {
         var10.printStackTrace();
         throw var10;
      } catch (IOException var11) {
         var11.printStackTrace();
         throw var11;
      }
   }

   public void generateFileUserDefined(String templateFileName, String type, Map data) throws TemplateException, IOException {
      try {
         String entityPackage = data.get("entityPackage").toString();
         String entityName = data.get("entityName").toString();
         String fileNamePath = this.getCodePath(type, entityPackage, entityName);
         String fileDir = StringUtils.substringBeforeLast(fileNamePath, "/");
         Template template = this.getConfigurationUserDefined().getTemplate(templateFileName);
         FileUtils.forceMkdir(new File(fileDir + "/"));
         Writer out = new OutputStreamWriter(new FileOutputStream(fileNamePath), CodeResourceUtil.SYSTEM_ENCODING);
         template.process(data, out);
         out.close();
      } catch (TemplateException var10) {
         var10.printStackTrace();
         throw var10;
      } catch (IOException var11) {
         var11.printStackTrace();
         throw var11;
      }
   }

   public static String getClassPath(Class clzz) {
      String path = clzz.getResource("/").getPath();
      if (SystemUtil.isHostWindows()){
         if (path.startsWith("/")){
            return path.substring(1);
         }
      }
      return path;
   }

   public String getCodePath(String type, String entityPackage, String entityName) {
      String path = this.getProjectPath();
      String codePath = "";
      if (this.packageStyle != null && CodeResourceUtil.PACKAGE_SERVICE_STYLE.equals(this.packageStyle)) {
         codePath = this.getCodePathServiceStyle(path, type, entityPackage, entityName);
      } else {
         codePath = this.getCodePathProjectStyle(path, type, entityPackage, entityName);
      }

      return codePath;
   }

   public void invoke(String templateFileName, String type) throws TemplateException, IOException {
      Map data = this.callBack.execute();
      this.generateFile(templateFileName, type, data);
   }

   public void invokeUserDefined(String templateFileName, String type) throws TemplateException, IOException {
      Map data = this.callBack.execute();
      this.generateFileUserDefined(templateFileName, type, data);
   }

   MyCodeGenerator generator;


   public void invokeNotFlt(String html, String type) throws TemplateException, IOException {
      Map data = this.callBack.execute();

      try {
         String entityPackage = data.get("entityPackage").toString();
         String entityName = data.get("entityName").toString();
         String fileNamePath = this.getCodePath(type, entityPackage, entityName);
         String fileDir = StringUtils.substringBeforeLast(fileNamePath, "/");
         FileUtils.forceMkdir(new File(fileDir + "/"));
         Configuration cfg = new Configuration();
         StringTemplateLoader loader = new StringTemplateLoader();
         loader.putTemplate(entityName, html);
         cfg.setTemplateLoader(loader);
         cfg.setDefaultEncoding("UTF-8");
         Template template = cfg.getTemplate(entityName);
         FileUtils.forceMkdir(new File(fileDir + "/"));
         Writer out = new OutputStreamWriter(new FileOutputStream(fileNamePath), CodeResourceUtil.SYSTEM_ENCODING);
         template.process(data, out);
         out.close();
      } catch (IOException var12) {
         var12.printStackTrace();
         throw var12;
      }
   }


   /**
    * Tiny模版解析
    */
   public void tinyTemplateGen(String templatePath) throws Exception{
      Map data = this.callBack.execute();
      String absolutePath= Paths.get(getClassPath(this.getClass()),CodeResourceUtil.FREEMARKER_CLASSPATH_USERDEFINED,templatePath).toString();

      File templateFile=Paths.get(absolutePath,"template.codegen.xml").toFile();
      if (templateFile.exists()){

         Context context = ContextFactory.getContext();
         String testJavaPath = Paths.get(projectPath , "src" , "test", "java").toString();
         String  testResourcePath = Paths.get(projectPath , "src" , "test", "java","resources").toString();
         context.put(CodeGenerator.JAVA_ROOT, Paths.get(projectPath , "src", "main" , "java" ).toString());
         context.put(CodeGenerator.JAVA_RES_ROOT, Paths.get(projectPath , "src", "main" , "resources" ).toString());
         context.put(CodeGenerator.JAVA_TEST_ROOT, testJavaPath);
         context.put(CodeGenerator.JAVA_TEST_RES_ROOT, testResourcePath);
         context.put(CodeGenerator.CODE_META_DATA, newMetadata);
         context.putAll(data);
         context.put(CodeGenerator.ABSOLUTE_PATH, absolutePath);
         generator.setInterateOutput(interateOutput);
         generator.generate(context);
      }else{
         throw new Exception("文件不存在");
      }
   }

   public static NewMetadata readFromXml(String fileName){
      return readFromXml(fileName);
   }



   public MyCodeGenerator.InterateOutput interateOutput;
}
